#ifndef __MAGIK_INFERENCEKIT_URANUS_UTILS_AISP_PROC_H__
#define __MAGIK_INFERENCEKIT_URANUS_UTILS_AISP_PROC_H__
#include "common/uranus_common_utils.h"
#include "core/uranus_tensor.h"
#include "core/uranus_type.h"

// ALG_PACK_START
namespace magik {
namespace uranus {

/*ft0: [1,184,320,16] 14bit(low)
 *ft1: [1,184,320,16] 14bit(low)
 *gamma: [1,184,320,1] 8bit
 *factor: 8bit
 *fpn: [1,184,320,16] 12bit(low)
 *output0: [1,184,320,16] 14bit(low)
 *output1: [1,368,640,4] 12bit(low)
 *tmp = (ft1 - ft0) * gamma
 *output0 = ft0 + (tmp >> 8) + ((tmp >> 7) & 0x1)
 *tmp = (output0 - ft1) * factor
 *outputA = ft1 + (tmp>>8) + ((tmp>>7) & 0x1)
 *if have_fpn is true:
 *  outputA = (outputA>>shift_count) - fpn
 *else
 *  outputA = (outputA>>shift_count) - int16_value
 *outputA = (outputA * int32_value) >> 10
 *outputA = clip(outputA, 0, max_val)
 *output1 = depth_to_space(outputA)
 *output1 = dpc_nhwc(output1) // remove dead pixels.
 *@Param sum_val: will be rewrite as sum(outputA)
 *@Param max_val: clip (output0>>shift_count)-fpn into 0~max_val
 *@Param shift_count: 2, for output0 >> shift_count
 *@Param threshold: value for dpc.
 */
URANUS_API int aisp_3d_post_merge_2d_pre(Tensor &ft0, Tensor &ft1, Tensor &gamma, Tensor &fpn,
                                         Tensor &output0, Tensor &output1, uint32_t &sum_val,
                                         uint16_t max_val, uint32_t shift_count, uint32_t threshold,
                                         bool have_fpn, uint8_t factor, int32_t int32_value,
                                         int32_t int16_value);

/*ft0: [1,184,320,16] 14bit(low)
 *ft1: [1,736,1280,1] 14bit(low)
 *gamma: [1,184,320,1] 8bit
 *factor: 8bit
 *fpn: [1,184,320,16] 12bit(low)
 *output0: [1,184,320,16] 14bit(low)
 *output1: [1,368,640,4] 12bit(low)
 *ft1_shift_count = 16 - ft1_bitwidth
 *ft1 = space_to_depth(ft1>>ft1_shift_count)
 *ft1 = space_to_depth(ft1)
 *tmp = (ft1 - ft0) * gamma
 *output0 = ft0 + (tmp >> 8) + ((tmp >> 7) & 0x1)
 *tmp = (output0 - ft1) * factor
 *outputA = ft1 + (tmp>>8) + ((tmp>>7) & 0x1)
 *if have_fpn is true:
 *  outputA = (outputA>>shift_count) - fpn
 *else
 *  outputA = (outputA>>shift_count) - int16_value
 *outputA = (outputA * int32_value) >> 10
 *outputA = clip(outputA, 0, max_val)
 *output1 = depth_to_space(outputA >> shift_count2)
 *if use_dpc:
 *  output1 = dpc_nhwc(output1) // remove dead pixels.
 *@Param sum_val: will be rewrite as sum(outputA)
 *@Param max_val: clip (output0>>shift_count)-fpn into 0~max_val
 *@Param shift_count: 2, for output0 >> shift_count
 *@Param threshold: value for dpc.
 */
URANUS_API int aisp_3d_pre_post_merge_2d_pre(Tensor &ft0, Tensor &ft1, Tensor &gamma, Tensor &fpn,
                                             Tensor &output0, Tensor &output1, uint32_t &sum_val,
                                             uint16_t max_val, uint32_t shift_count,
                                             uint32_t threshold, bool have_fpn, uint8_t factor,
                                             int32_t int32_value, bool use_dpc,
                                             int16_t *int16_value, uint32_t shift_count2 = 0);

/*ft0: [1,184,320,16] 14bit(low)
 *ft1: [1,736,1280,1] 14bit(low)
 *gamma: [1,184,320,1] 8bit
 *factor: 8bit
 *fpn: [1,184,320,16] 12bit(low)
 *output0: [1,184,320,16] 14bit(low)
 *output1: [1,736,1280,1] 12bit(high)
 *ft1_shift_count = 16 - ft1_bitwidth
 *ft1 = space_to_depth(ft1>>ft1_shift_count)
 *ft1 = space_to_depth(ft1)
 *tmp = (ft1 - ft0) * gamma
 *output0 = ft0 + (tmp >> 8) + ((tmp >> 7) & 0x1)
 *tmp = (output0 - ft1) * factor
 *outputA = ft1 + (tmp>>8) + ((tmp>>7) & 0x1)
 *if have_fpn is true:
 *   outputA = (outputA>>shift_count) - fpn
 *else
 *   outputA = (outputA>>shift_count) - int16_value
 *outputA = outputA * int32_value >> 10
 *outputA = clip(outputA, 0, max_val)
 *outputA = depth_to_space(outputA)
 *output1 = depth_to_space(outputA << shift_count2)
 *@Param max_val: clip (output0>>shift_count)-fpn into 0~max_val
 *@Param shift_count: 2, for output0 >> shift_count
 *@Param start, end: for output1 blk comb.
 *@Param shift_count2: for output1 << shift_count2
 */
URANUS_API int aisp_3d_pre_post(Tensor &ft0, Tensor &ft1, Tensor &gamma, Tensor &fpn,
                                Tensor &output0, Tensor &output1, uint16_t max_val,
                                uint32_t shift_count, bool have_fpn, int start, int end,
                                uint8_t factor, int32_t int32_value, int16_t *int16_value,
                                uint32_t shift_count2 = 4);

/*input0: [1, 540, 960, 4] 16bit(uint16)
 *input1: [1, 540, 960, 4] 16bit(int16)
 *output: [1, 1080, 1920, 1] 16bit(uint16)
 *coef_i = coef_i << 1
 *output0 = (input0 << 4) - ((input1 * coef_i) >> 10)
 *output1 = clip(output0, 0, 2^16-1)
 *output = depth_to_space(output0)
 */
URANUS_API int aisp_2d_post_v2(Tensor &input0, Tensor &input1, Tensor &output, int16_t coef_i);

/*input: [1,736,1280,1] 16bit
 *output: [1,184,320,16] 12bit
 *output = space_to_depth(input>>shift_count)
 *output = space_to_depth(output)
 *@Param shift_count: 4 (for 12bit input) or 2 (for 14bit input)
 */
URANUS_API int aisp_3d_pre(Tensor &input, Tensor &output, uint32_t shift_count);

} // namespace uranus
} // namespace magik
// ALG_PACK_END
#endif //__MAGIK_INFERENCEKIT_URANUS_UTILS_AISP_PROC_H__
